package com.teamsun.controller;

import com.alibaba.dubbo.remoting.TimeoutException;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.teamsun.cache.CacheManager;
import com.teamsun.entity.*;
import com.teamsun.exception.ServiceException;
import com.teamsun.rptcfg.*;
import com.teamsun.service.ICallThirdService;
import com.teamsun.service.IDownloadService;
import com.teamsun.service.ISaveRptService;
import com.teamsun.service.IShowRptService;
import com.teamsun.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;

/**
 * <p>展示报表信息Controller</p>
 */
@Controller
@RequestMapping("/rptTools/showRpt")
public class ShowRptController implements ApplicationContextAware{

    private WebApplicationContext context;

    @Autowired
    private ISaveRptService saveRptService;

    @Autowired
    private IShowRptService showRptService;

    @Autowired
    private IDownloadService downloadService;

    @Autowired
    private CacheManager cacheManager;

    /**
     * 报表信息初始化
     * @param request
     * @return
     */
    @RequestMapping("/showRptIndex")
    public String showRptIndex(HttpServletRequest request) {
        // 获取报表ID
        String rptId = request.getParameter("rptId");
        String token = "";
        String userId = "";  // 接入报表的第三方系统传入的用户ID
        String userKey = "";  // 接入报表的第三方系统传入的用户ID的参数key
        String isDrill = "0";  // 是否是下钻页面
        try {
            // 前台对参数做了2次加密,后台需做2次解密
            rptId = Base64Util.decodeToString(rptId);
            rptId = Base64Util.decodeToString(rptId);
            rptId = rptId.substring(0, rptId.length() - 6);
        } catch (Exception e) {
            return "error";
        }

        // 获取缓存的报表配置信息
        BaseRpt rptInfo = null;
        String thirdSysCode = request.getParameter(Constants.SYSCODEPARAM);  // 接入报表的第三方系统传入的系统编码
        Object rptObj = cacheManager.getRptCache(rptId);
        if(rptObj != null) {
            // 报表配置信息在缓存中
            rptInfo = (BaseRpt) rptObj;

            String accessSysCode = rptInfo.getAccessSysCode();
            String offLineUserKey = accessSysCode + "." + Constants.UERKEY;
            // 外部系统传入用户名key
            userKey = (String) cacheManager.getCacheValue(offLineUserKey);
            userId = request.getParameter(userKey);
            isDrill = request.getParameter("isDirll");
        } else {
            try {
                // 报表信息不在缓存中，则需要从数据库中查询
                BaseRpt baseRpt = saveRptService.queryRptCfgById(rptId);
                if(baseRpt != null) {
                    // 读取报表配置文件信息
                    String rptCfgFilePath = (String) cacheManager.getCacheValue(Constants.RPTCFGPATH);
                    //String rptCfgFilePath = request.getSession().getServletContext().getRealPath("/WEB-INF/rptConfig");
                    String fileName = "RPT_" + rptId + ".xml";
                    File rptCfgFile = new File(rptCfgFilePath + "/" + fileName);
                    InputStream inputStream = new FileInputStream(rptCfgFile);
                    ParseRptCfg parseRptCfg = new ParseRptCfg();
                    rptInfo = parseRptCfg.parseRptCfg(inputStream, fileName);
                    rptInfo.setRptId(baseRpt.getRptId());
                    rptInfo.setRptName(baseRpt.getRptName());
                    rptInfo.setDataSource(baseRpt.getDataSource());
                    rptInfo.setRptHeader(baseRpt.getRptHeader());
                    rptInfo.setRptToken(baseRpt.getRptToken());
                    rptInfo.setAccessSysCode(baseRpt.getAccessSysCode());

                    String accessSysCode = baseRpt.getAccessSysCode();
                    String offLineUserKey = accessSysCode + "." + Constants.UERKEY;
                    // 外部系统传入用户名key
                    userKey = (String) cacheManager.getCacheValue(offLineUserKey);
                    userId = request.getParameter(userKey);
                    isDrill = request.getParameter("isDirll");

                    // 缓存报表数据
                    cacheManager.addRptCache(rptId, rptInfo);
                } else {
                    return "error";
                }
            } catch (Exception e) {
                e.printStackTrace();
                return "error";
            }
        }

        // 如果报表中有冻结列，则需要将表头信息中的冻结列删除
        // 报表表头信息(JSON格式)
        String tableHeaderJson = rptInfo.getRptHeader();
        // 冻结列信息
        List<BaseRptColumn> lockColumns = rptInfo.getLockColumns();
        if(lockColumns != null && lockColumns.size() > 0 && !rptInfo.getResetHeader()) {
            List<List<TableHeader>> headers = JSON.parseObject(tableHeaderJson, new TypeReference<List<List<TableHeader>>>(){});
            for(int i=0; i<lockColumns.size(); i++) {
                BaseRptColumn rptColumn = (BaseRptColumn) lockColumns.get(i);
                String field = rptColumn.getAliasField();

                // 删除表头中的冻结列信息
                boolean skipLoop = false;
                for(List<TableHeader> tableHeaders : headers) {
                    for(TableHeader tableHeader : tableHeaders) {
                        if(field.equals(tableHeader.getField())) {
                            tableHeaders.remove(tableHeader);
                            skipLoop = true;
                            break;
                        }
                    }
                    if(skipLoop) {
                        break;
                    }
                }

                PropertyFilter filter = new PropertyFilter() {
                    @Override
                    public boolean apply(Object object, String name, Object value) {
                        if((name.equals("sortable") && "false".equals(String.valueOf(value))) || ((name.equals("hidden") && "false".equals(String.valueOf(value)))) || (name.equals("colspan") && "0".equals(String.valueOf(value))) || ((name.equals("rowspan") && "0".equals(String.valueOf(value)))) || ((name.equals("width") && "0".equals(String.valueOf(value))))) {
                            return false;
                        }
                        return true;
                    }
                };
                tableHeaderJson = JSON.toJSONString(headers,filter);
                rptInfo.setResetHeader(true);
                rptInfo.setRptHeader(tableHeaderJson);
            }
        }

        List<BaseRptColumn> conditionColumns = rptInfo.getConditionColumns();

        Map<String, String> conditionParmMap = new HashMap<String, String>();

        //如果是自定义报表，则需要获取自定义报表默认选择的条件
        String selfReport = request.getParameter(Constants.SELFREPORT);  // 报表是否是自定义报表
        if(Constants.YES.equals(selfReport)) {
            // 获取自定义报表的传入参数
            Enumeration<String> parameterNames = request.getParameterNames();
            String params = "";
            while (parameterNames.hasMoreElements()) {
                String paramName = parameterNames.nextElement();
                params = params + paramName + ",";
            }
            if(params.endsWith(",")) {
                params = params.substring(0, params.length() - 1);
            }

            // 获取自定义报表的参数值
            parseRptParamToMap(params, request, conditionParmMap);
        }

        // 解析初始化参数
        String conditionParams = rptInfo.getInitCondition();
        parseRptParamToMap(conditionParams, request, conditionParmMap);
        // 解析第三方参数
        String thirdParams = rptInfo.getThirdParam();
        Map<String, String> thirdParmMap = new HashMap<String, String>();
        parseRptParamToMap(thirdParams, request, thirdParmMap);

        // 获取查询条件的默认值
        if(conditionColumns != null && conditionColumns.size() > 0) {
            // 获取报表的数字动态格式化配置信息(个计、万计信息)
            BaseRptColumn dynamicRpt = rptInfo.getDynamicNum();
            String formatType = "";
            if(dynamicRpt != null) {
                Map<String, String> dynamicMap = dynamicRpt.getOptionValue();
                for(Map.Entry<String, String> entry : dynamicMap.entrySet()) {
                    formatType = entry.getKey();
                    break;
                }
            }

            // 设置查询条件的默认值
            for(BaseRptColumn conditionColumn : conditionColumns) {
                String conditionType = conditionColumn.getConditionType();  // 查询条件类型
                String aliesField = conditionColumn.getAliasField();  // 查询条件字段
                String dynamicFomat = conditionColumn.getDynamicFormat();  // 动态格式化方式(个计、万计信息)
                String numberFormat = conditionColumn.getNumberFormat();  // 数字格式化方式
                boolean hasDefaultValue = false;
                List<String> multiSelectDefault = new ArrayList<String>();  // 保存多选下拉框默认值


                // 如果是自定义报表，初始化初始值及状态
                // 初始默认值都为空，如果用户定义了初始查询条件，会在后续步骤中赋初始值
                if(Constants.YES.equals(selfReport)) {
                    conditionColumn.setReadOnly(Constants.NO);  // 查询条件默认可编辑
                    conditionColumn.setSelfDefineValue("");
                    conditionColumn.setSelfDefineName("");
                    conditionColumn.setSelfDefineValueEnd("");
                    conditionColumn.setSelfDefineMultiSelect(new HashMap<String, Boolean>());
                }

                // 如果报表传入初始化参数，则需要将初始化参数作为默认值赋给查询条件
                if(Constants.CONDITIONTYPE_TREE.equals(conditionType)) {  // 查询类型为树
                    String relateName = conditionColumn.getRelateName();
                    String selectedName = conditionParmMap.get(relateName);
                    String nameKey = aliesField + "Id";
                    String codeKey = "hid_" + aliesField;
                    String defaultName = conditionParmMap.get(nameKey);
                    String defaultValue = conditionParmMap.get(codeKey);
                    String confirmValue = conditionParmMap.get(aliesField);

                    if(StringUtils.isNotBlank(confirmValue) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(confirmValue)) {
                        if(StringUtils.isNotEmpty(defaultValue)) {
                            String[] values = defaultValue.split(",");
                            String[] names = defaultName.split(",");
                            for(int i=0; i<values.length; i++) {
                                if(confirmValue.equals(values[i])) {
                                    if(Constants.YES.equals(selfReport)) {
                                        // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                        conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                        conditionColumn.setSelfDefineValue(values[i]);
                                        conditionColumn.setSelfDefineName(names[i]);
                                    } else {
                                        conditionColumn.setDefaultValue(values[i]);
                                        conditionColumn.setDefaultName(names[i]);
                                    }
                                    hasDefaultValue = true;
                                    break;
                                }
                            }
                        }
                    } else {
                        if(StringUtils.isNotBlank(selectedName) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(selectedName)) {
                            if(StringUtils.isNotEmpty(defaultName)) {
                                String[] values = defaultValue.split(",");
                                String[] names = defaultName.split(",");
                                for(int i=0; i<names.length; i++) {
                                    if(selectedName.equals(names[i])) {
                                        if(Constants.YES.equals(selfReport)) {
                                            // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                            conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                            conditionColumn.setSelfDefineValue(values[i]);
                                            conditionColumn.setSelfDefineName(names[i]);
                                        } else {
                                            conditionColumn.setDefaultName(names[i]);
                                            conditionColumn.setDefaultValue(values[i]);
                                        }
                                        hasDefaultValue = true;
                                        break;
                                    }
                                }
                            }
                        } else {
                            if (StringUtils.isNotBlank(defaultName)) {
                                if(Constants.YES.equals(selfReport)) {
                                    conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                    conditionColumn.setSelfDefineName(defaultName);
                                } else {
                                    conditionColumn.setDefaultName(defaultName);
                                }
                                hasDefaultValue = true;
                            }
                            if (StringUtils.isNotBlank(defaultValue)) {
                                if(Constants.YES.equals(selfReport)) {
                                    // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态日
                                    conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                    conditionColumn.setSelfDefineValue(defaultValue);
                                } else {
                                    conditionColumn.setDefaultValue(defaultValue);
                                }
                                hasDefaultValue = true;
                            }
                        }
                    }
                } else if(Constants.CONDITIONTYPE_DATE_RANGE.equals(conditionType) || Constants.CONDITIONTYPE_VALUE_RANGE.equals(conditionType)) {
                    String keyStart = aliesField + "_start";
                    String keyEnd = aliesField + "_end";
                    String valueStart = conditionParmMap.get(keyStart);
                    String valueEnd = conditionParmMap.get(keyEnd);
                    String relateName = conditionColumn.getRelateName();
                    String selectedData = conditionParmMap.get(relateName);

                    double dblValueStart = 0;
                    double dblValueEnd = 0;

                    // 报表下钻时，传入的数字均为个计，如果当前报表的查询条件需要已万计、千计等显示，则将相关列的值格式化
                    if(dynamicRpt != null && Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                        if(StringUtils.isNotBlank(valueStart)) {
                            dblValueStart = Double.valueOf(valueStart);
                        }
                        if(StringUtils.isNotBlank(valueEnd)) {
                            dblValueEnd = Double.valueOf(valueEnd);
                        }
                        if(formatType.indexOf("0.") != -1) {
                            int nodeLength = formatType.length() - 2;
                            if(nodeLength == 1) {  // 十计
                                dblValueStart = dblValueStart / 10;
                                dblValueEnd = dblValueEnd / 10;
                            } else if(nodeLength == 2) {  // 百计
                                dblValueStart = dblValueStart / 100;
                                dblValueEnd = dblValueEnd / 100;
                            } else if(nodeLength == 3) {  // 千计
                                dblValueStart = dblValueStart / 1000;
                                dblValueEnd = dblValueEnd / 1000;
                            } else if(nodeLength == 4) {  // 万计
                                dblValueStart = dblValueStart / 10000;
                                dblValueEnd = dblValueEnd / 10000;
                            }
                        }
                    }

                    // 报表下钻时，百分比为除以100后的值(如20%传入的值为0.2)，如果当前报表的查询条件需要以百分比显示，则将相关列的值格式化
                    if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                        if(StringUtils.isNotBlank(valueStart)) {
                            dblValueStart = Double.valueOf(valueStart);
                        }
                        if(StringUtils.isNotBlank(valueEnd)) {
                            dblValueEnd = Double.valueOf(valueEnd);
                        }
                        dblValueStart = dblValueStart * 100;
                        dblValueEnd = dblValueEnd * 100;
                    }

                    if(StringUtils.isNotBlank(valueStart)) {
                        if(dynamicRpt != null &&  Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(formateNumber(dblValueStart));
                            } else {
                                conditionColumn.setDefaultValue(formateNumber(dblValueStart));
                            }
                        }else if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(formateNumber(dblValueStart));
                            } else {
                                conditionColumn.setDefaultValue(formateNumber(dblValueStart));
                            }
                        } else {
                            if(StringUtils.isNotBlank(selectedData) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(selectedData)) {
                                valueStart = selectedData;
                            }
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态日
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(valueStart);
                            } else {
                                conditionColumn.setDefaultValue(valueStart);
                            }
                        }
                    } else {
                        if(Constants.CONDITIONTYPE_DATE_RANGE.equals(conditionType)) {
                            CommonUtils.setDefaultDateStart(conditionColumn);
                        }
                    }
                    if(StringUtils.isNotBlank(valueEnd)) {
                        if(dynamicRpt != null && Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValueEnd(formateNumber(dblValueEnd));
                            } else {
                                conditionColumn.setDefaultValueEnd(formateNumber(dblValueEnd));
                            }
                        } else if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态日
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValueEnd(formateNumber(dblValueEnd));
                            } else {
                                conditionColumn.setDefaultValueEnd(formateNumber(dblValueEnd));
                            }
                        } else {
                            if(StringUtils.isNotBlank(selectedData) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(selectedData)) {
                                valueEnd = selectedData;
                            }
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValueEnd(valueEnd);
                            } else {
                                conditionColumn.setDefaultValueEnd(valueEnd);
                            }
                        }
                    } else {
                        if(Constants.CONDITIONTYPE_DATE_RANGE.equals(conditionType)) {
                            CommonUtils.setDefaultDateEnd(conditionColumn);
                        }
                    }
                } else if(Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {  // 多选下拉框
                    String multiValue = conditionParmMap.get(aliesField);
                    if(StringUtils.isBlank(multiValue)) {
                        multiValue = conditionColumn.getDefaultValue();
                    }
                    if(StringUtils.isNotBlank(multiValue) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(multiValue)) {
                        String[] values = multiValue.split(",");
                        for(String value : values) {
                            double dblDefaultValue = 0;
                            String defaultValue = "";
                            if(dynamicRpt != null &&  Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                                if(StringUtils.isNotBlank(value)) {
                                    dblDefaultValue = Double.valueOf(value);
                                }
                                if(formatType.indexOf("0.") != -1) {
                                    int nodeLength = formatType.length() - 2;
                                    if(nodeLength == 1) {  // 十计
                                        dblDefaultValue = dblDefaultValue / 10;
                                    } else if(nodeLength == 2) {  // 百计
                                        dblDefaultValue = dblDefaultValue / 100;
                                    } else if(nodeLength == 3) {  // 千计
                                        dblDefaultValue = dblDefaultValue / 1000;
                                    } else if(nodeLength == 4) {  // 万计
                                        dblDefaultValue = dblDefaultValue / 10000;
                                    }
                                }
                                defaultValue = formateNumber(dblDefaultValue);
                            } else if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                                if(StringUtils.isNotBlank(value)) {
                                    dblDefaultValue = Double.valueOf(value);
                                }
                                dblDefaultValue = dblDefaultValue * 100;
                                defaultValue = formateNumber(dblDefaultValue);
                            } else {
                                defaultValue = value;
                            }

                            if(StringUtils.isNotBlank(defaultValue)) {
                                multiSelectDefault.add(defaultValue);
                            }
                        }
                    }
                } else {
                    String defaultValue = conditionParmMap.get(aliesField);
                    if(StringUtils.isBlank(defaultValue)) {
                        if(Constants.CONDITIONTYPE_DATE.equals(conditionType)) {
                            CommonUtils.setDefaultDate(conditionColumn);
                        }
                        defaultValue = conditionColumn.getDefaultValue();
                    }
                    double dblDefaultValue = 0;

                    if(dynamicRpt != null &&  Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                        if(StringUtils.isNotBlank(defaultValue)) {
                            dblDefaultValue = Double.valueOf(defaultValue);
                        }
                        if(formatType.indexOf("0.") != -1) {
                            int nodeLength = formatType.length() - 2;
                            if(nodeLength == 1) {  // 十计
                                dblDefaultValue = dblDefaultValue / 10;
                            } else if(nodeLength == 2) {  // 百计
                                dblDefaultValue = dblDefaultValue / 100;
                            } else if(nodeLength == 3) {  // 千计
                                dblDefaultValue = dblDefaultValue / 1000;
                            } else if(nodeLength == 4) {  // 万计
                                dblDefaultValue = dblDefaultValue / 10000;
                            }
                        }
                    }

                    if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                        if(StringUtils.isNotBlank(defaultValue)) {
                            dblDefaultValue = Double.valueOf(defaultValue);
                        }
                        dblDefaultValue = dblDefaultValue * 100;
                    }
                    if(StringUtils.isNotBlank(defaultValue)) {
                        if(dynamicRpt != null &&  Constants.DYNAMICFORMAT_VALUE.equals(dynamicFomat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态日
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(formateNumber(dblDefaultValue));
                            } else {
                                conditionColumn.setDefaultValue(formateNumber(dblDefaultValue));
                            }
                        } else if(StringUtils.isNotBlank(numberFormat) && Constants.NUMBERFORMATER_PERCENT_100.equals(numberFormat)) {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(formateNumber(dblDefaultValue));
                            } else {
                                conditionColumn.setDefaultValue(formateNumber(dblDefaultValue));
                            }
                        } else {
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(defaultValue);
                            } else {
                                conditionColumn.setDefaultValue(defaultValue);
                            }
                        }
                    }
                }

                // 查询列中，如果查询类型是下拉框/多选下拉框且下拉框的值需要从数据库中查询
                if(Constants.CONDITIONTYPE_SELECT.equals(conditionType) || Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                    Map<String, String> option = conditionColumn.getOptionValue();
                    // 下拉框的值未配置，则需要从数据库中查询
                    if(option == null || option.size() == 0) {
                        SelectDim selectDim = conditionColumn.getSelectDim();
                        if(selectDim != null) {
                            Map<String, String> selectOption = showRptService.querySelectValue(selectDim, rptInfo);

                            // 如果是多选下拉框，前台默认添加全选选项，所以需要将查询结果中的[请选择]选项删除
                            if(Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                                selectOption.remove("");
                            }
                            conditionColumn.setOptionValue(selectOption);
                        }
                    }
                } else if(Constants.CONDITIONTYPE_TREE.equals(conditionType)) {
                    // 如果查询类型为树且树指定默认值，则查询树的根节点信息(如果查询条件是树，那么默认值只能是跟节点)
                    TreeDim treeDim = conditionColumn.getTreeDim();
                    if(Constants.YES.equals(treeDim.getNeedDefauleValue()) && !hasDefaultValue) {
                        // 指定默认值，查询树数据的根节点信息
                        String rightParam = treeDim.getRightParam();
                        String parentRightParam = treeDim.getParentRightParam();
                        String root = treeDim.getRootCode();
                        List<Map<String, Object>> treeDatas = new ArrayList<Map<String, Object>>();
                        if(StringUtils.isNotBlank(rightParam)) {
                            String rightValue = thirdParmMap.get(rightParam);
                            treeDatas = showRptService.queryTreeData(treeDim, rightValue, "", "", rptInfo);
                        } else if(StringUtils.isNotBlank(parentRightParam)) {
                            String parentRightValue = thirdParmMap.get(parentRightParam);
                            treeDatas = showRptService.queryTreeData(treeDim, "", parentRightValue, "", rptInfo);
                        } else if(StringUtils.isNotBlank(root)) {
                            treeDatas = showRptService.queryTreeData(treeDim, "", "", root, rptInfo);
                        } else {
                            treeDatas = showRptService.queryTreeData(treeDim, "", "", "", rptInfo);
                        }
                        if(treeDatas != null && treeDatas.size() > 0) {
                            Map<String, Object> rootData = treeDatas.get(0);
                            String code = (String) rootData.get("code");
                            String name = (String) rootData.get("name");
                            if(Constants.YES.equals(selfReport)) {
                                // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                                conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                conditionColumn.setSelfDefineValue(code);
                                conditionColumn.setSelfDefineName(name);
                            } else {
                                conditionColumn.setDefaultValue(code);
                                conditionColumn.setDefaultName(name);
                            }
                        }
                    }
                }

                // 如果是多选下拉框设置多选下拉框的默认值
                if(Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                    Map<String, String> options = conditionColumn.getOptionValue();
                    Map<String, Boolean> defaultOptions = new HashMap<String, Boolean>();
                    if(options != null && options.size() > 0) {
                        for(Map.Entry<String, String> entry : options.entrySet()) {
                            String key = entry.getKey();
                            if(multiSelectDefault.contains(key)) {
                                defaultOptions.put(key, true);
                            } else {
                                defaultOptions.put(key, false);
                            }
                        }

                        if(Constants.YES.equals(selfReport)) {
                            // 如果是自定义报表，则设置用户自定义的默认值，并将查询条件置为不可编辑的状态
                            for(Map.Entry<String, Boolean> entry : defaultOptions.entrySet()) {
                                Boolean isSelect = entry.getValue();
                                if(isSelect) {
                                    conditionColumn.setReadOnly(Constants.SELFREPORT_CONDITION_STATE);
                                    break;
                                }
                            }
                            conditionColumn.setSelfDefineMultiSelect(defaultOptions);
                        } else {
                            conditionColumn.setMutiSelectDefault(defaultOptions);
                        }
                    }
                }
            }
        }

        // 如果列需要下钻，做特殊处理
        String columnArray = rptInfo.getRptHeader().replaceAll("\"function", "function");
        columnArray = columnArray.replaceAll("}\"", "}");

        columnArray = columnArray.replaceAll("\"", "\\\\\'");  // 报表展示列

        String lockColumnArray = rptInfo.getRptLockHeader().replaceAll("\"", "\\\\\'");  // 报表冻结列

        // 重置查询列的排列顺序，将必须输入的查询列放置在最前端
        List<BaseRptColumn> resetConditionColumn = new ArrayList<BaseRptColumn>();
        List<BaseRptColumn> notNeedColumns = new ArrayList<BaseRptColumn>();  // 保存非必输条件
        List<BaseRptColumn> showColumns = new ArrayList<BaseRptColumn>();  // 保存需展示的条件列(报表配置中isHideCondition="1"时有用)
        if(conditionColumns != null && conditionColumns.size() > 0) {
            for(BaseRptColumn conditionColumn : conditionColumns) {
                if(Constants.YES.equals(conditionColumn.getIsNeed())) {
                    resetConditionColumn.add(conditionColumn);
                    showColumns.add(conditionColumn);
                } else {
                    notNeedColumns.add(conditionColumn);
                }
            }
            resetConditionColumn.addAll(notNeedColumns);
        }
        //String conditionArray = JSON.toJSONString(rptInfo.getConditionColumns());

        // 如果查询条件列均为非必输选项，则默认展示4个条件列(报表配置中isHideCondition="1"时有用)
        if(Constants.YES.equals(rptInfo.getIsHideCondition())) {
            if(showColumns.size() == 0) {
                int count = 1;
                for(int i=0; i<notNeedColumns.size(); i++) {
                    if(count <= 4) {
                        BaseRptColumn rptColumn = notNeedColumns.get(i);
                        showColumns.add(rptColumn);
                        if (Constants.CONDITIONTYPE_DATE_RANGE.equals(rptColumn.getConditionType())) {
                            count = count + 2;
                        } else {
                            count = count + 1;
                        }
                    }
                }
                notNeedColumns.removeAll(showColumns);
            } else {
                List<BaseRptColumn> showConditions = new ArrayList<BaseRptColumn>();
                int count = 1;
                for(int i=0; i<showColumns.size(); i++) {
                    if(count <=4) {
                        BaseRptColumn rptColumn = showColumns.get(i);
                        showConditions.add(rptColumn);
                        if (Constants.CONDITIONTYPE_DATE_RANGE.equals(rptColumn.getConditionType())) {
                            count = count + 2;
                        } else {
                            count = count + 1;
                        }
                    }
                }

                if(count < 4) {
                    for(int i=0; i<notNeedColumns.size(); i++) {
                        if(count <= 4) {
                            BaseRptColumn rptColumn = notNeedColumns.get(i);
                            showConditions.add(rptColumn);
                            if (Constants.CONDITIONTYPE_DATE_RANGE.equals(rptColumn.getConditionType())) {
                                count = count + 2;
                            } else {
                                count = count + 1;
                            }
                        }
                    }
                    notNeedColumns.removeAll(showConditions);

                    showColumns.clear();
                    showColumns.addAll(showConditions);
                } else {
                    showColumns.removeAll(showConditions);
                    notNeedColumns.addAll(showColumns);

                    showColumns.clear();
                    showColumns.addAll(showConditions);
                }
            }
        }

        rptInfo.setConditionColumns(resetConditionColumn);
        String conditionArray = JSON.toJSONString(resetConditionColumn);
        conditionArray = conditionArray.replace("\'", "\\'");
        conditionArray = conditionArray.replace("\"", "\'");  // 报表查询列

        // 获取外部系统传入的参数
        String thirdParam = rptInfo.getThirdParam();
        List<Map<String, String>> thirdParms = new ArrayList<Map<String, String>>();
        parseRptParam(thirdParam, request, thirdParms);
        String jsonParam = JSON.toJSONString(thirdParms);
        if(StringUtils.isNotBlank(jsonParam)) {
            jsonParam = jsonParam.replaceAll("\"", "\\\\\'");
        }

        // 获取报表初始化查询需要的参数(例如:报表是由其他报表下钻而来，则报表初始化查询时需要根据下钻参数查询)
        String conditionParam = rptInfo.getInitCondition();
        List<Map<String, String>> conditionParms = new ArrayList<Map<String, String>>();
        parseRptParam(conditionParam, request, conditionParms);
        String jsonCondition = JSON.toJSONString(conditionParms);
        if(StringUtils.isNotBlank(jsonCondition)) {
            jsonCondition = jsonCondition.replaceAll("\"", "\'");
        }

        request.setAttribute("rptInfo", rptInfo);  // 报表信息
        request.setAttribute("columns", columnArray);  // 报表列信息
        request.setAttribute("lockColumns", lockColumnArray);  // 报表冻结列信息
        request.setAttribute("conditionColumns", conditionArray);  // 报表查询条件列
        request.setAttribute("rptId", rptId);  // 报表ID
        request.setAttribute("thirdParams", jsonParam);  // 第三方传入参数
        request.setAttribute("initConditions", jsonCondition);  // 报表初始化查询参数
        request.setAttribute("userId", userId);  // 报表接入系统传入的用户ID
        request.setAttribute("userKey", userKey);  // 报表接入系统传入的用户ID的参数key
        request.setAttribute("isDrill", isDrill);  // 是否是下钻页面
        request.setAttribute(Constants.SYSCODEPARAM, thirdSysCode);

        // 报表配置中isHideCondition="1"时有用(用于控制查询条件的显示/隐藏)
        request.setAttribute("showColumns", showColumns);
        request.setAttribute("notNeedColumns", notNeedColumns);

        if(Constants.YES.equals(rptInfo.getNeedAnalysis())) {  // 报表展示需要包含左侧分析菜单
            String selfDefineDim = request.getParameter(Constants.RPTDIM_KEY);  // 自定义报表中，用户选择的维度
            String selfDefineIdx = request.getParameter(Constants.RPTIDX_KEY);  // 自定义报表中，用户选择的指标

            List<BaseRptColumn> dimColumns = new ArrayList<BaseRptColumn>();  // 维度列
            List<BaseRptColumn> sumIdxColumns = new ArrayList<BaseRptColumn>();  // 报表所有指标
            List<BaseRptColumn> idxColumns = new ArrayList<BaseRptColumn>();  // 无分类指标列
            Map<String, List<BaseRptColumn>> idxGroupMap = new HashMap<String, List<BaseRptColumn>>();  // 分类指标
            List<String> groupInfo = new ArrayList<String>();  // 分类信息
            List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();  // 报表所有展示列
            if(rptColumns != null && rptColumns.size() > 0) {
                for(BaseRptColumn rptColumn : rptColumns) {
                    rptColumn.setSelfDefineSelect(Constants.NO);
                    String colType = rptColumn.getColType();
                    String aliasField = rptColumn.getAliasField();
                    if(Constants.YES.equals(colType)) {
                        // 对于下钻页面,查看是否有包含下钻维度
                        String colValue = conditionParmMap.get(aliasField);
                        if(StringUtils.isNotBlank(colValue)) {
                            rptColumn.setIsSelect(Constants.YES);
                        }

                        // 对于自定义报表，如果用户选择了维度，则需要默认勾选
                        if(Constants.YES.equals(selfReport) && StringUtils.isNotBlank(selfDefineDim)) {
                            if(selfDefineDim.contains(aliasField)) {
                                rptColumn.setSelfDefineSelect(Constants.YES);
                            }
                        }

                        dimColumns.add(rptColumn);
                    } else if(Constants.NO.equals(colType)) {
                        // 对于自定义报表，如果用户选择了维度，则需要默认勾选
                        if(Constants.YES.equals(selfReport) && StringUtils.isNotBlank(selfDefineIdx)) {
                            if(selfDefineIdx.contains(aliasField)) {
                                rptColumn.setSelfDefineSelect(Constants.YES);
                            }
                        }

                        sumIdxColumns.add(rptColumn);

                        // 指标是否存在分类信息
                        String group = rptColumn.getGroup();
                        if(StringUtils.isNotBlank(group)) {  // 存在分类信息，保存分类指标信息
                            if(!idxGroupMap.containsKey(group)) {
                                groupInfo.add(group);
                                List<BaseRptColumn> groupColumns = new ArrayList<BaseRptColumn>();
                                groupColumns.add(rptColumn);
                                idxGroupMap.put(group, groupColumns);
                            } else {
                                List<BaseRptColumn> groupColumns = idxGroupMap.get(group);
                                groupColumns.add(rptColumn);
                            }
                        } else {  // 不存在分类信息，保存无分类指标
                            idxColumns.add(rptColumn);
                        }
                    }
                }
            }
            request.setAttribute("sumIdxColumns", sumIdxColumns);  // 报表全部指标列
            request.setAttribute("idxColumns", idxColumns);  // 报表无分类指标列
            request.setAttribute("idxGroupColumnns", idxGroupMap);  // 报表分类指标
            request.setAttribute("groupInfo", groupInfo);  // 报表分类指标
            request.setAttribute("dimColumns", dimColumns);  // 报表维度列

            if(Constants.YES.equals(selfReport)) {
                return "selfDefineAnalysisRptInfo";
            } else {
                return "analysisRptInfo";
            }
        } else if(Constants.NO.equals(rptInfo.getNeedAnalysis()) && Constants.NO.equals(rptInfo.getDrillLayout())) {  // 报表展示无左侧分析菜单
            if(Constants.YES.equals(selfReport)) {
                return "selfDefineShowRptInfo";
            } else {
                return "showRptInfo";
            }
        } else {
            if(Constants.YES.equals(selfReport)) {
                return "selfDefineShowRptInfo";
            } else {
                return "showRptInfo";
            }
        }
    }

    /**
     * 查询报表数据
     */
    @RequestMapping("/queryRptInfo")
    @ResponseBody
    public JSONObject queryRptInfo(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject();
        try {
            String rptId = request.getParameter("rptId");  // 报表ID

            // 获取缓存的报表配置信息
            BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
            List<BaseRptColumn> conditionColumn = rptInfo.getConditionColumns();

            // 获取查询参数
            Map<String, String> paramMap = RequestParamToMap.convertToMap(request, conditionColumn);

            // 防SQL注入
            AntiSQLInject.filter(paramMap);

            /**
             * 查询报表数据
             */
            RptResult rptResult = new RptResult();
            String needPage = rptInfo.getNeedPage();  // 是否需要分页
            if (Constants.YES.equals(needPage)) {
                // 分页查询数据
                int page = ServletRequestUtils.getIntParameter(request, "page", 1);
                int rows = ServletRequestUtils.getIntParameter(request, "rows", 0);
                int startIndex = (page - 1) * rows + 1;
                int endIndex = page * rows;
                rptResult = showRptService.queryRptInfoByPage(rptInfo, paramMap, startIndex, endIndex, rows);
            } else {
                // 查询数据
                rptResult = showRptService.queryRptInfo(rptInfo, paramMap);
            }

            jsonObject.put("rows", rptResult.getResultList());
            jsonObject.put("total", rptResult.getTotalCount());
            return jsonObject;
        } catch (RpcException e) {
            jsonObject.put("rows", new ArrayList<Map<String, String>>());
            jsonObject.put("total", 0);
            jsonObject.put("status", "0");
            jsonObject.put("msg", "查询数据量过大，请使用离线下载或控制查询条件减小查询量");
            return jsonObject;
        } catch (ServiceException e) {
            jsonObject.put("rows", new ArrayList<Map<String, String>>());
            jsonObject.put("total", 0);
            jsonObject.put("status", "0");
            jsonObject.put("msg", e.getMessage());
            return jsonObject;
        } catch (Exception e) {
            jsonObject.put("rows", new ArrayList<Map<String, String>>());
            jsonObject.put("total", 0);
            jsonObject.put("status", "0");
            jsonObject.put("msg", "查询失败，请联系管理员");
            return jsonObject;
        }
    }

    /**
     * 报表导出Excel
     * 报表导出查询的数据量比较大，不宜用dubbbo进行前后端调用
     * 所以将数据查询及Excel文件的生成在dubbo后端完成，前端负责读取文件并将文件下载
     * @param request
     * @param response
     */
    @RequestMapping("/downLoadExcel")
    @ResponseBody
    public void downLoadExcel(HttpServletRequest request, HttpServletResponse response) {
        try {
            String rptId = request.getParameter("rptId");  // 报表ID
            // 获取缓存的报表配置信息
            BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
            List<BaseRptColumn> conditionCol = rptInfo.getConditionColumns();

            // 获取查询条件
            Map<String, String> paramMap = RequestParamToMap.convertToMap(request, conditionCol);
            String selectRptIdx = paramMap.get("rptIdx");  // 选中的指标
            String selectRptDim = paramMap.get("rptDim");  // 选中的维度

            // 表头Excel文件路径
            String rptHeaderFilePath = (String) cacheManager.getCacheValue(Constants.RPTHEADERPATH);

            String fileName = rptInfo.getRptName() + ".xlsx";

            // 查询数据并生成Excel文件
            // 防SQL注入
            AntiSQLInject.filter(paramMap);

            String rptHeaderFileName = "RPT_" + rptId + ".xlsx";
            // 读取Excel模板并复制
            InputStream inputStream = new FileInputStream(rptHeaderFilePath + "/" + rptHeaderFileName);

            String cacheKey = UUID.randomUUID().toString() + "-" + System.currentTimeMillis();

            RptResult rptResult = downloadService.queryDownloadData(rptInfo, paramMap, cacheKey);
            int totalCount = rptResult.getTotalCount();
            List<Map<String, Object>> rptDatas = new ArrayList<Map<String, Object>>();
            if(totalCount <= Constants.BATCH_CNT) {
                rptDatas.addAll(rptResult.getResultList());
            } else {
                // 数据量过大，分批获取数据
                for (int i = 0; i <= totalCount; i+=Constants.BATCH_CNT) {
                    List<Map<String, Object>> pageList = downloadService.queyrDataFromCache(cacheKey, i, i + Constants.BATCH_CNT);
                    if(!CollectionUtils.isEmpty(pageList)) {
                        rptDatas.addAll(pageList);
                    }
                }
            }

            // 下载数据获取结束，删除缓存数据
            downloadService.deleteCache(cacheKey);

            List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();

            // 将JSON字符串转换成TableHeader对象
            String rptHeaderJson = rptInfo.getRptHeader();
            List<List<TableHeader>> headers = JSON.parseObject(rptHeaderJson, new TypeReference<List<List<TableHeader>>>(){});
            int headerRows = headers.size();  // 表头行数

            String filePath = getRealPath();
            File newFile = new File(filePath, fileName);

            byte[] copyBytes = new byte[1024];
            int copyLen = 0;
            OutputStream outputStream = new FileOutputStream(newFile);
            while ((copyLen = inputStream.read(copyBytes)) != -1) {
                outputStream.write(copyBytes, 0, copyLen);
            }
            outputStream.flush();
            inputStream.close();
            outputStream.close();

            // 新文件写入数据
            FileInputStream fio = new FileInputStream(newFile);
            XSSFWorkbook workbook = new XSSFWorkbook(fio);
            XSSFSheet sheet = workbook.getSheetAt(0);

            FileOutputStream fos = new FileOutputStream(newFile);
            XSSFRow row = sheet.getRow(1);
            if(row == null) {
                row = sheet.createRow(1);
            }
            XSSFCell cell = row.getCell(0);
            if(cell == null) {
                cell = row.createCell(0);
            }

            List<String> idxList = new ArrayList<String>();
            List<String> dimList = new ArrayList<String>();
            if(StringUtils.isNotBlank(selectRptIdx)) {
                String[] idxs = selectRptIdx.split(",");
                idxList = Arrays.asList(idxs);
            }
            if(StringUtils.isNotBlank(selectRptDim)) {
                String[] dims = selectRptDim.split(",");
                for(String dim : dims) {
                    dimList.add(dim);
                }
                // 获取级联维度
                for(BaseRptColumn rptColumn : rptColumns) {
                    String aliasField = rptColumn.getAliasField();
                    String cascadeField = rptColumn.getCascade();
                    if(dimList.contains(aliasField) && StringUtils.isNotBlank(cascadeField)) {
                        dimList.add(cascadeField);
                    }
                }
            }
            if(rptDatas != null && rptDatas.size() > 0) {
                List<String> titleList = rptInfo.getExcelHeader();  // 按顺序获取Excel表头名称
                List<String> usedTitle = new ArrayList<String>();
                Set<String> percentTitle = new HashSet<String>();
                String needSum = rptInfo.getNeedSum();
                int dataSize = 0;
                if(Constants.YES.equals(needSum)) {
                    dataSize = rptDatas.size() - 1;
                } else {
                    dataSize = rptDatas.size();
                }
                XSSFCellStyle cellStyle = workbook.createCellStyle();
                XSSFCellStyle intStyle = workbook.createCellStyle();
                XSSFDataFormat dataFormat = workbook.createDataFormat();
                cellStyle.setDataFormat(dataFormat.getFormat("#,##0.00"));
                intStyle.setDataFormat(dataFormat.getFormat("#0"));
                DecimalFormat percentFormat = new DecimalFormat("#.##%");
                DecimalFormat decimalFormat = new DecimalFormat("0.00");

                for(int i=0; i<dataSize; i++) {
                    row = sheet.createRow(i + headerRows);
                    Map<String, Object> rptData = rptDatas.get(i);
                    usedTitle.clear();
                    for(int k=0; k<titleList.size(); k++) {
                        String excelTitle = titleList.get(k);
                        for(int j=0; j<rptColumns.size(); j++) {
                            BaseRptColumn rptColumn = rptColumns.get(j);
                            String title = rptColumn.getName();
                            String key = rptColumn.getAliasField();
                            if(title.equals(excelTitle) && !usedTitle.contains(key)) {
                                String colType= rptColumn.getColType();
                                String conditionType = rptColumn.getConditionType();
                                cell =row.createCell(k);
                                String strValue = "";
                                if(rptData.get(key) != null) {
                                    strValue = String.valueOf(rptData.get(key));

                                    // 如果列是查询列且类型为下拉框，则需要转义(将编码转换为名称)
                                    if(Constants.CONDITIONTYPE_SELECT.equals(conditionType) || Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                                        Map<String, String> optionValue = rptColumns.get(j).getOptionValue();
                                        strValue = optionValue.get(strValue);
                                    }
                                }

                                // 判断是否为数字
                                boolean isNumber = CommonUtils.isNumberic(strValue);
                                if(isNumber) {
                                    Double value = Double.parseDouble(strValue);
                                    if(Constants.NUMBERFORMATER_PERCENT_100.equals(rptColumn.getNumberFormat())) {
                                        String percent = percentFormat.format(value);
                                        cell.setCellValue(percent);
                                        percentTitle.add(key);
                                    } else if(Constants.NUMBERFORMATER_PERCENT.equals(rptColumn.getNumberFormat())) {
                                        String percent = decimalFormat.format(value);
                                        cell.setCellValue(percent + "%");
                                    } else {
                                        if(strValue.indexOf(".") > -1) {
                                            cell.setCellStyle(cellStyle);
                                            cell.setCellValue(value);
                                        } else {
                                            cell.setCellStyle(intStyle);
                                            cell.setCellValue(value);
                                        }
                                    }
                                } else {
                                    cell.setCellValue(strValue);
                                }

                                // 如果指标或维度未选中，在导出Excel时，将相关列设置为隐藏
                                if(StringUtils.isNotBlank(selectRptIdx)) {
                                    if(Constants.NO.equals(colType) && !idxList.contains(key)) {
                                        sheet.setColumnWidth(k, 0);
                                        //sheet.setColumnHidden(j, true);
                                    }
                                }
                                if(StringUtils.isNotBlank(selectRptDim)) {
                                    if(Constants.YES.equals(colType) && !dimList.contains(key)) {
                                        sheet.setColumnWidth(k, 0);
                                        //sheet.setColumnHidden(j, true);
                                    }
                                }
                                usedTitle.add(key);
                                break;
                            }
                        }
                    }
                }
                // 如果报表是汇总报表，则需要额外导出汇总行
                if(Constants.YES.equals(needSum)) {
                    Map<String, Object> rptData = rptDatas.get(dataSize);
                    row = sheet.createRow(dataSize + headerRows);
                    for(int m=0; m<usedTitle.size(); m++) {
                        String key = usedTitle.get(m);
                        cell =row.createCell(m);
                        String strValue = "";
                        if(rptData.get(key) != null) {
                            strValue = String.valueOf(rptData.get(key));
                        }

                        // 判断是否为数字
                        boolean isNumber = CommonUtils.isNumberic(strValue);
                        if(isNumber) {
                            Double value = Double.parseDouble(strValue);
                            if(percentTitle.contains(key)) {
                                String percent = percentFormat.format(value);
                                cell.setCellValue(percent);
                            } else {
                                if(strValue.indexOf(".") > -1) {
                                    cell.setCellStyle(cellStyle);
                                    cell.setCellValue(value);
                                } else {
                                    cell.setCellStyle(intStyle);
                                    cell.setCellValue(value);
                                }
                            }
                        } else {
                            cell.setCellValue(strValue);
                        }
                    }
                }
            }
            workbook.write(fos);
            fos.flush();
            fos.close();
            fio.close();

            InputStream fis = new FileInputStream(newFile);
            // 下载报表文件
            byte[] bytes = new byte[1024];
            int len = 0;
            OutputStream load = response.getOutputStream();
            String userAgent = request.getHeader("User-Agent");
            String encodeFileName = "";
            // 针对IE或者以IE为内核的浏览器：
            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                encodeFileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                // 非IE浏览器的处理：
                encodeFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            /*encodeFileName = encodeFileName.replace("%28", "(");
            encodeFileName = encodeFileName.replace("%29", ")");*/
            response.setBufferSize(512);
            response.setContentType("application/vnd.ms-excel");
            response.addHeader("Content-disposition", "attachment; filename=" + encodeFileName);
            while ((len = fis.read(bytes)) > 0) {
                load.write(bytes, 0, len);
            }
            load.flush();
            load.close();
            fis.close();

            newFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 重置报表表头(选中左侧菜单中的指标时，重置报表表头)
     */
    @RequestMapping("/resetRptHeader")
    @ResponseBody
    public JSONObject resetRptHeader(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject();
        String rptId = request.getParameter("rptId");  // 报表ID
        String rptIdx = request.getParameter("rptIdx");  // 选中指标
        String rptDim = request.getParameter("rptDim");  // 选中维度
        String dynamicFormatter = request.getParameter("dynamicFormate");  // 获取数据动态格式化信息
        List<String> rptDimList = new ArrayList<String>();
        List<String> rptIdxList = new ArrayList<String>();

        // 获取缓存的报表配置信息=
        BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
        String analysis = rptInfo.getNeedAnalysis();

        if(StringUtils.isNotBlank(rptIdx)) {
            String[] rptIdxs = rptIdx.split(",");
            rptIdxList = Arrays.asList(rptIdxs);
        } else {
            // 如果前台未勾选指标，那么默认加载所有指标
            List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();
            for(int i=0; i<rptColumns.size(); i++) {
                BaseRptColumn rptColumn = (BaseRptColumn) rptColumns.get(i);
                if(Constants.NO.equals(rptColumn.getColType())) {  // 指标
                    rptIdxList.add(rptColumn.getAliasField());
                }
            }
        }
        if(StringUtils.isNotBlank(rptDim)) {
            String[] rptDims = rptDim.split(",");
            rptDimList = Arrays.asList(rptDims);
        } else {
            // 如果报表不是分析型报表，那么默认加载所有维度
            if(StringUtils.isBlank(analysis) || Constants.NO.equals(analysis)) {
                List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();
                for(int i=0; i<rptColumns.size(); i++) {
                    BaseRptColumn rptColumn = (BaseRptColumn) rptColumns.get(i);
                    if(Constants.YES.equals(rptColumn.getColType())) {  // 维度
                        rptDimList.add(rptColumn.getAliasField());
                    }
                }
            }
        }



        // 报表表头信息
        String tableHeaderJson = rptInfo.getRptHeader();
        List<List<TableHeader>> headers = JSON.parseObject(tableHeaderJson, new TypeReference<List<List<TableHeader>>>(){});


        try {
            for(List<TableHeader> tableHeaders : headers) {
                for(TableHeader tableHeader : tableHeaders) {
                    String field = tableHeader.getField();

                    // 根据选择的计数方式重置表头单位
                    int colSpan = tableHeader.getColspan();
                    if(colSpan == 0) {
                        //String title = tableHeader.getTitle();
                        String title = tableHeader.getAliasTitle();
                        String unit = tableHeader.getUnit();
                        if(StringUtils.isNotBlank(unit) && tableHeader.isDynamicFormatter()) {  // 如果列为动态格式化列则需要根据选择的计数方式重置表头
                            //title = title.substring(0,title.lastIndexOf("("));
                            title = RptCfgUtils.resetHeaderTitle(dynamicFormatter, unit,title);
                            tableHeader.setTitle(title);
                        }
                    }

                    // 重置表头(只显示选中的指标和维度)
                    if(StringUtils.isNotBlank(field)) {
                        if (!rptIdxList.contains(field) && !rptDimList.contains(field)) {
                            tableHeader.setHidden(true);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        PropertyFilter filter = new PropertyFilter() {
            @Override
            public boolean apply(Object object, String name, Object value) {
                if((name.equals("sortable") && "false".equals(String.valueOf(value))) || ((name.equals("hidden") && "false".equals(String.valueOf(value)))) || (name.equals("colspan") && "0".equals(String.valueOf(value))) || ((name.equals("rowspan") && "0".equals(String.valueOf(value)))) || ((name.equals("width") && "0".equals(String.valueOf(value))))) {
                    return false;
                }
                return true;
            }
        };
        tableHeaderJson = JSON.toJSONString(headers,filter);
        tableHeaderJson = tableHeaderJson.replaceAll("\"function", "function");
        tableHeaderJson = tableHeaderJson.replaceAll("}\"", "}");
        //JSONArray jsonArray = JSONArray.parseArray(tableHeaderJson);
        jsonObject.put("tableHeader", tableHeaderJson);
        return jsonObject;
    }

    /**
     * 离线下载
     * @param request
     * @return
     */
    @RequestMapping("/offLineDownLoad")
    @ResponseBody
    public JSONObject offLineDownLoad(HttpServletRequest request) {
        String rptId = request.getParameter("rptId");  // 报表ID
        String itemCode = request.getParameter(Constants.SYSCODEPARAM);
        BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
        String accessSysCode = rptInfo.getAccessSysCode();  // 报表接入系统

        if(StringUtils.isEmpty(accessSysCode)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("status", "0");
            jsonObject.put("msg", "报表未配置接入系统,请联系管理员");
            return jsonObject;
        }

        // 离线下载实现类
        // 由于报表工具会对接不同的系统，不同系统对于离线下载的实现方式可能会有差异，
        // 所以目前的实现方式是根据报表接入系统的不同，动态的选择实现类
        String implClassKey = accessSysCode + "." + Constants.OFFLINEDOWNLOADIMPL;
        String implClass = (String) cacheManager.getCacheValue(implClassKey);
        ICallThirdService callThirdService = (ICallThirdService) context.getBean(implClass);

        // 离线下载外部服务地址
        String offLineDownLoadURL = accessSysCode + "." + Constants.OFFLINEDOWNLOADURL;
        String offLineURL = (String) cacheManager.getCacheValue(offLineDownLoadURL);

        // 封装调用外部服务的请求
        IRequestInfo requestInfo = callThirdService.wrapRequestInfo(request, itemCode);

        // 调用外部请求
        HttpResult httpResult = callThirdService.callThirdService(offLineURL, requestInfo);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("status", httpResult.getStateCode());
        jsonObject.put("msg", httpResult.getBody());
        return jsonObject;
    }

    /**
     * 自定义报表
     * @param request
     * @return
     */
    @RequestMapping("/selfDefine")
    @ResponseBody
    public JSONObject selfDefine(HttpServletRequest request) {
        String rptId = request.getParameter("rptId");  // 报表ID
        String itemCode = request.getParameter(Constants.SYSCODEPARAM);
        BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
        String accessSysCode = rptInfo.getAccessSysCode();  // 报表接入系统

        if(StringUtils.isEmpty(accessSysCode)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("status", "0");
            jsonObject.put("msg", "报表未配置接入系统,请联系管理员");
            return jsonObject;
        }

        // 自定义报表实现类
        // 由于报表工具会对接不同的系统，不同系统对于自定义报表的实现方式可能会有差异，
        // 所以目前的实现方式是根据报表接入系统的不同，动态的选择实现类
        String implClassKey = accessSysCode + "." + Constants.SELFDEFINEIMPL;
        String implClass = (String) cacheManager.getCacheValue(implClassKey);
        ICallThirdService callThirdService = (ICallThirdService) context.getBean(implClass);

        // 自定义报表外部服务地址
        String selfDefineURLKey = accessSysCode + "." + Constants.SELFDEFINEURL;
        String selfDefineURL = (String) cacheManager.getCacheValue(selfDefineURLKey);

        // 封装调用外部服务的请求
        IRequestInfo requestInfo = callThirdService.wrapRequestInfo(request, itemCode);

        // 调用外部请求
        HttpResult httpResult = callThirdService.callThirdService(selfDefineURL, requestInfo);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("status", httpResult.getStateCode());
        jsonObject.put("msg", httpResult.getBody());
        return jsonObject;
    }

    /**
     * 解析报表参数(包括第三方传入参数和报表初始化参数)
     * @param rptParam 报表参数
     * @param request
     * @param conditionList 保存参数名和参数值
     */
    private void parseRptParam(String rptParam, HttpServletRequest request, List<Map<String, String>> conditionList) {
        try {
            if(StringUtils.isNotBlank(rptParam)) {
                String[] params = rptParam.split(",");
                for(int i=0; i<params.length; i++) {
                    String param = params[i];
                    String paramValue = request.getParameter(param);
                    if(StringUtils.isNotBlank(paramValue)) {
                        paramValue = URLDecoder.decode(paramValue, "UTF-8");
                        if(paramValue.contains("'")) {
                            paramValue = paramValue.replaceAll("'","");
                        }
                        Map<String, String> paramMap = new HashMap<String, String>();
                        paramMap.put("paramName", param);
                        paramMap.put("paramValue", paramValue);
                        conditionList.add(paramMap);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析报表参数(包括第三方传入参数和报表初始化参数)
     * @param rptParam 报表参数
     * @param request
     * @param conditionMap 保存参数名和参数值
     */
    private void parseRptParamToMap(String rptParam, HttpServletRequest request, Map<String, String> conditionMap) {
        try {
            if(StringUtils.isNotBlank(rptParam)) {
                String[] params = rptParam.split(",");
                for(int i=0; i<params.length; i++) {
                    String param = params[i];
                    String paramValue = request.getParameter(param);
                    if(StringUtils.isNotBlank(paramValue)) {
                        // URLDecoder会将+和空格转码，所以在URLDecoder.decode前，需要将+和空格提前转码
                        if(paramValue.contains("+")) {
                            paramValue = paramValue.replace("+", "%2b");
                        }

                        /*if(paramValue.contains(" ")) {
                            param = paramValue.replace(" ", "%20");
                        }*/
                        paramValue = URLDecoder.decode(paramValue, "UTF-8");
                        if(paramValue.contains("'")) {
                            paramValue = paramValue.replaceAll("'","");
                        }
                        conditionMap.put(param, paramValue);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = (WebApplicationContext) applicationContext;
    }

    /**
     * 格式化数字，将1.0格式化为1
     * @param number
     * @return
     */
    private String formateNumber(double number) {
        String strNum = String.valueOf(number);
        if(strNum.endsWith(".0") || strNum.endsWith(".00")) {
            strNum = strNum.substring(0, strNum.indexOf("."));
        }
        return strNum;
    }

    private String getRealPath() {
        String path = this.getClass().getClassLoader().getResource("/").getPath();
        String[] paths = path.split("/");
        String realPath = "";
        for (int i = 0; i < paths.length - 2; i++) {
            realPath += paths[i] + "/";
        }
        System.out.println("======" + realPath);
        return realPath;
    }
}
